package com.cian.controller;


import com.cian.entity.History;
import com.cian.entity.dto.ClientCommodityDTO;
import com.cian.entity.dto.CommodityForStockAddDTO;
import com.cian.entity.dto.StockDTO;
import com.cian.service.impl.*;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;

/**
 * <p>
 * 子终端对应的商品库存在mysql的持久表 前端控制器
 * </p>
 *
 * @author Cian
 * @since 2021-03-09
 */
@RestController
@RequestMapping("//stock")
public class StockController {
    @ApiModelProperty("表示查询的时候一页最大的数量")
    private static final int MAX_PAGE_NUMBER = 5;
    @Autowired
    HistoryServiceImpl historyService;
    @Autowired
    CommodityInformServiceImpl commodityInformService;
    @Autowired
    StockServiceImpl stockService;
    @Autowired
    RedisImpl rediService;
    @Autowired
    SubsystemServiceImpl subsystemService;

    @RequestMapping("/get/add")
    public CommodityForStockAddDTO getStockAndCommodity(@RequestParam("server_code") String serverCode){
        CommodityForStockAddDTO commodityForStockAddDTO = new CommodityForStockAddDTO();
        commodityForStockAddDTO.setCommodity(commodityInformService.selectStockAddInfrom());
        commodityForStockAddDTO.setStock(stockService.getSubsystemStockForCommodity(serverCode));
        return commodityForStockAddDTO;
    }

    @RequestMapping("/option")
    public Boolean addAndDeleteForStock(@RequestParam("server_code") String serverCode,
                                        @RequestParam("add") Integer[] add,
                                        @RequestParam("delete") Integer[] delete){
        try{
            if(add.length > 0){
                stockService.selectStockByList(serverCode, add);
            }
            if(delete.length > 0){
                stockService.deleteStockByList(serverCode, delete);
            }
            // 更新Redis中的值
            List<StockDTO> list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
            // 默认五分钟过期
            rediService.setStockByCode(serverCode, list, 5*60*1000);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @RequestMapping("/obtain")
    public List<StockDTO> obtainData(@RequestParam("server_code") String serverCode,
                                     @RequestParam("next_page") int nextPage){
        // 前端的nextPage从1开始，后台需要进行处理
        nextPage = nextPage <= 0 ? 0: nextPage - 1;
        // 判断是否在Redis中存在缓存，如果存在则返回Redis的值
        List<StockDTO> list = rediService.getStockByCode(serverCode, nextPage, MAX_PAGE_NUMBER);
        if(list == null){
            // 判断出Redis不存在该项, 在mysql取出后，更新Redis中的值
            list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
            if (list == null) return null;
            // 默认五分钟过期
            rediService.setStockByCode(serverCode, list, 5*60*1000);
        }
        list = stockService.getStockByCode(serverCode, nextPage, MAX_PAGE_NUMBER);
        return list;
    }

    @RequestMapping("/delete")
    public Boolean deleteDate(@RequestParam("server_code") String serverCode, @RequestParam("delete") Integer[] delete){
        try{
            // 删除后，查询数据库，将更新覆盖到Redis中
            stockService.deleteStockByList(serverCode, delete);
            // 获取全部的数据
            List<StockDTO> list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
            // 将数据保存全部保存到Redis中，缓存时间为5min
            rediService.setStockByCode(serverCode, list, 5*60*1000);
            return true;
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @RequestMapping("/obtain/client")
    public List<ClientCommodityDTO> getClientCommodityList(@RequestParam("server_code") String serverCode){
        return stockService.getClientCommodityList(serverCode);
    }


    @RequestMapping("/obtain/commodity")
    public StockDTO getCommodityInform(@RequestParam("server_code") String serverCode, @RequestParam("co_Id") int coId){
        // 通过co_Id 来循环遍历查找，查不到后就通过mysql精确查找，并且覆盖redis
        StockDTO item = rediService.finderForCoId(serverCode, coId);
        if(item == null){
            // 说明当前Redis中不存在该项，需要进行更新覆盖
            // 获取全部的数据
            List<StockDTO> list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
            if(list == null) return null;
            // 将数据保存全部保存到Redis中，缓存时间为5min
            rediService.setStockByCode(serverCode, list, 5*60*1000);
            return rediService.finderForCoId(serverCode, coId);
        }
        return item;
    }

    @RequestMapping("/buying")
    public boolean buyCommodity(@RequestParam("server_code") String serverCode, @RequestParam("co_Id") int coId,
                                @RequestParam("buy_number") int num){
        // 购买的业务模块，当前不设置购买方式，如传入的值查询存在库存，则进行变化，否则传出false
        // 该模块必须直接和mysql进行交互，防止Redis的不同步问题
        StockDTO stock = stockService.getStockInform(serverCode, coId);
        if (stock == null) return false;
        if(stock.getAmount() - num <= 0){
            List<StockDTO> list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
            rediService.setStockByCode(serverCode, list, 5*60*1000);
            return false;
        }
        stockService.buyingSetting(serverCode, coId, stock.getAmount() - num);
        List<StockDTO> list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
        rediService.setStockByCode(serverCode, list, 5*60*1000);
        // TODO 当前采用单线程的方式记录历史，以为若是需要改进，则需要在这里改变为多线程的模式
        // 获取server_code所属的账户名
        String account = subsystemService.selectByServerCode(serverCode).getServerAccount();
        // 将销售历史记录到数据库中
        historyService.changeStock(account, serverCode, new Date(), coId, num);
        // 覆盖缓存Redis中的历史记录
        History history = historyService.getHistory(account, serverCode, new Date(), coId);
        rediService.setHistory(account, serverCode, new Date(), history);
        return true;
    }

    @RequestMapping("/update")
    public boolean updateRow(@RequestParam("server_code") String serverCode, @RequestParam("co_Id") int co_Id,
                             @RequestParam("price") double price, @RequestParam("stock") int stock){
        boolean ret =  stockService.updateStockByCode(serverCode, co_Id, price, stock);
        List<StockDTO> list = stockService.getStockByCodeForAll(serverCode, MAX_PAGE_NUMBER);
        rediService.setStockByCode(serverCode, list, 5*60*1000);
        // TODO 当前采用单线程的方式记录历史，以为若是需要改进，则需要在这里改变为多线程的模式
        // 获取server_code所属的账户名
        String account = subsystemService.selectByServerCode(serverCode).getServerAccount();
        // 将销售历史记录到数据库中
        historyService.changeInput(account, serverCode, new Date(), co_Id, stock);
        // 覆盖缓存Redis中的历史记录
        History history = historyService.getHistory(account, serverCode, new Date(), co_Id);
        rediService.setHistory(account, serverCode, new Date(), history);
        return ret;
    }
}

